package com.yc.junit;

import java.lang.annotation.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class MathBizTest {
    MathBiz biz;

    @Test(1)
    public void test1() {
        System.out.println("-------- test1 --------");
        int res = biz.add(1, 1);
        Assert.assertEquals(2, res);
    }

    @Test(3)
    public void test2() {
        System.out.println("-------- test2 --------");
        int res = biz.sub(1, 1);
        Assert.assertEquals(0, res);
    }

    @Test(5)
    public void test3() {
        System.out.println("-------- test3 --------");
        int res = biz.mul(1, 1);
        Assert.assertEquals(1, res);
    }

    @Test(2)
    public void test4() {
        System.out.println("-------- test4 --------");
        int res = biz.div(1, 1);
        Assert.assertEquals(1, res);
    }

    @Test(4)
    public void test5() {
        System.out.println("-------- test5 --------");
        int res = biz.pow(2);
        Assert.assertEquals(4, res);
    }

    // 每个测试方法执行前执行的方法
    @Before
    public void before() {
        System.out.println("======== before =======");
        biz = new MathBiz();
    }

    // 每个测试方法执行后执行的方法
    @After
    public void after() {
        System.out.println("======== after =======");
        biz = null;

    }


    public static void main(String[] args) {

        //完成单元测试
        Object tester = new MathBizTest();

        //提取方法进行分类
        List<Method> tests = new ArrayList<>();
        List<Method> befores = new ArrayList<>();
        List<Method> afters = new ArrayList<>();

        Class<?> aClass = tester.getClass();
        Method[] methods = aClass.getDeclaredMethods();


        //循环完成
        for (Method method : methods) {
            if (method.getAnnotation(Test.class) != null) {
                tests.add(method);
            } else if (method.getAnnotation(After.class) != null) {
                afters.add(method);
            }
            if (method.getAnnotation(Before.class) != null) {
                befores.add(method);
            }
        }

        //对test方法进行排序
        tests.sort(Comparator.comparingInt(m -> m.getAnnotation(Test.class).value()));

        int correctCount = 0;
        int errorCount = 0;
        int exceptionCount = 0;

        //先执行before方法
        for (Method test : tests) {
            for (Method before : befores) {
                try {
                    before.invoke(tester);
                } catch (Exception e) {
                    throw new RuntimeException("before 方法执行错误", e);
                }
            }
            //执行测试方法
            try {
                test.invoke(tester);
                //统计为正确的方法
                correctCount++;  // 统计正确的方法
            } catch (IllegalAccessException e) {
                throw new RuntimeException("测试方法访问错误");
            } catch (InvocationTargetException e) {
                Throwable cause = e.getCause();
                if (cause instanceof AssertException) {
                    //统计为错误方法
                    errorCount++;  // 统计错误的方法
                } else {
                    //统计为异常方法
                    exceptionCount++;  // 统计异常的方法
                }
                System.out.println(cause);

            }
            //再执行after方法
            for (Method after : afters) {
                try {
                    after.invoke(tester);
                } catch (Exception e) {
                    throw new RuntimeException("after 方法执行错误", e);
                }
            }
        }


        //统计结果
        System.out.println();
        System.out.printf("正确: %d, 错误: %d, 异常: %d%n", correctCount, errorCount, exceptionCount);
    }

}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Test {
    int value();
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Before {

}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface After {

}


//断言
class Assert {
    public static void assertEquals(Object o1, Object o2) {
        if (o1 == null && o2 == null) {
            return;  //表示正确
        } else if ((o1 == null || o2 == null) || (o1.equals(o2) == false)) {
            throw new AssertException("结果不正确");
        }
    }
}


//自定义异常
class AssertException extends RuntimeException {
    public AssertException(String msg) {
        super(msg);
    }
}
